package com.zjw.zy.heart.wbsocket.socket;

import com.zjw.zy.heart.configuration.TaskPool;
import com.zjw.zy.heart.smi.JustWithIt;
import com.zjw.zy.heart.userpool.IUserPool;
import com.zjw.zy.heart.utils.LogUtils;
import com.zjw.zy.heart.wbsocket.WsDispatcher;
import com.zjw.zy.heart.wbsocket.WsSender;
import com.zjw.zy.heart.wbsocket.WsStreamProcessor;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@ServerEndpoint("/user/this_is_secret_link/connect/zjw_love_zy_forever_and_forever99999999/{username}")
public class WsSocketService {

    private static final String TAG = "WsSocketService";
    /**
     * 用户连接池
     */
    private static IUserPool userPool;

    private static WsDispatcher dispatcher;

    private String clientUsername;

    private static WsChecker checker;

    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) {
        if (!checker.checkConnect(username)) {
            LogUtils.e(TAG, "invalid connect " + username);
            WsSender.close(session);
            return;
        }
        LogUtils.d(TAG, "onOpen " + username);
        userPool.connect(username, session);
        clientUsername = username;
        TaskPool.getConcurrentPool().execute(() -> {
            dispatcher.dispatchWsOpen(session, username);
        });
    }

    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        LogUtils.d(TAG, "onClose " + clientUsername);
        if (clientUsername != null) {
            userPool.disConnect(clientUsername);
            TaskPool.getConcurrentPool().execute(() -> {
                dispatcher.dispatchWsClose(session, closeReason);
            });
        }
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        LogUtils.e(TAG, "onError: " + clientUsername, throwable);
    }


    @OnMessage
    public void onMessage(Session session, String message) {
        LogUtils.e(TAG, "receive message : " + message);

        TaskPool.getConcurrentPool().execute(() -> {
            WsMessage wsMessage = WsMessage.obtainFromString(message);
            dispatcher.dispatchWsMessage(wsMessage);
            wsMessage.recycle();
        });
    }

    @OnMessage
    public void onMessage(Session session, byte[] bytes) {
        //for big data
        LogUtils.e(TAG, "receive big data message ");

        WsStreamProcessor.acceptBytes(bytes, obj -> {
            TaskPool.getConcurrentPool().execute(() -> {
                dispatcher.dispatchWsMessage(obj);
                obj.recycle();
            });
        });
    }

    @Autowired
    public void setUserPool(IUserPool userPool) {
        WsSocketService.userPool = userPool;
    }

    @Autowired
    public void setDispatcher(WsDispatcher dispatcher) {
        WsSocketService.dispatcher = dispatcher;
    }

    @Autowired
    public void setChecker(WsChecker checker) {
        WsSocketService.checker = checker;
    }
}
